package utility.geometry;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Polygon;
import entity.month.PointCoordinate;

import java.util.List;

/**
 * @author lit
 * @date 2018/3/20.
 */
public class ProcessPoint {
    /**
     * 获取多个点的中心点
     * @param pointList 经度和维度值组成数组后进一步组成的list
     */
    public static PointCoordinate getCenterPoint(List<PointCoordinate> pointList){
        int size = pointList.size();
        int[] rank = new int[size];

        for(int i=0; i < size-1; i++){
            for(int j = i+1; j < size; j++ ){
                if(getDistance(pointList.get(i), pointList.get(j)) <= 150){
                    rank[i]++;
                    rank[j]++;
                }
            }
        }

        //检查int数组中value值最大对应的index
        int max = 0;
        for(int k=0; k < size; k++){
            if(rank[k] > rank[max]){
                max = k;
            }
        }
        return pointList.get(max);
    }

    /**
     * 获取两点的距离
     * @param lon1 点1的经度
     * @param lat1 点1的纬度
     * @param lon2 点2的经度
     * @param lat2 点2的纬度
     * @return
     */
    public static double getDistance(double lon1,double lat1,double lon2,double lat2){
        if(lon1 > 0 && lon2 > 0 && lat1 > 0 && lat2 > 0){
            //经度差
            double lonDiff = getRadian(lon1) - getRadian(lon2);
            //纬度差
            double latDiff = getRadian(lat1) - getRadian(lat2);

            double result = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(latDiff / 2), 2) + Math.cos(getRadian(lat1)) * Math.cos(getRadian(lat2)) * Math.pow(Math.sin(lonDiff / 2), 2)));
            return result * 6378.137 * 1000;
        }else{
            return -1;
        }

    }

    /**
     * 获取两点的距离
     * @param p0 点0
     * @param p1 点1
     * @return
     */
    public static double getDistance(PointCoordinate p0, PointCoordinate p1){
        //经度差
        double lonDiff = getRadian(p0.getLon()) - getRadian(p1.getLon());
        //纬度差
        double latDiff = getRadian(p0.getLat()) - getRadian(p1.getLat());

        double result = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(latDiff / 2), 2) + Math.cos(getRadian(p0.getLat())) * Math.cos(getRadian(p0.getLat())) * Math.pow(Math.sin(lonDiff / 2), 2)));
        return result * 6378.137 * 1000;
    }

    /**
     * 获取工作地的多点中心点（只适用于对IDBox项目中对多点求工作地）
     * @param pointList
     * @return
     */
    public static PointCoordinate getWorkCenterPoint(List<PointCoordinate> pointList){
        int size = pointList.size();
        //标记点符合条件的次数
        int[] rank = new int[size];
        //标记车辆停放的时间
        int[] timeInterval = new int[size];
        int[] totalTime = new int[size];
        for(int m = 0; m < size; m++){
            timeInterval[m] = pointList.get(m).getTimeInterval();
            totalTime[m] = timeInterval[m];
        }

        for(int i=0; i < size; i++){
            for(int j = i+1; j < size; j++ ){
                if(getDistance(pointList.get(i).getLon(),pointList.get(i).getLat(),pointList.get(j).getLon(),pointList.get(j).getLat()) <= 150){
                    rank[i]++;
                    rank[j]++;
                    totalTime[i] += timeInterval[j];
                    totalTime[j] += timeInterval[i];
                }
            }
        }

        //查找出现次数在8次以上，同时总时间大于2400分钟的最大次数的index
        int maxValue = 8;
        int maxIndex = -1;
        int maxTotalTime = 2400;
        for(int k=0; k < size; k++){
            if(rank[k] >= maxValue && totalTime[k] >= maxTotalTime){
                maxIndex = k;
                maxValue = rank[k];
                maxTotalTime = totalTime[k];
            }
        }
        if(maxIndex > -1){
            return pointList.get(maxIndex);
        }else{
            return null;
        }
    }

    private static double getRadian(double temp){
        return temp * Math.PI / 180;
    }


    /**
     * 判断点在面中
     * @param point
     * @param geometry
     * @return
     */
    public static boolean polygonContainsPoint(com.vividsolutions.jts.geom.Point point, Geometry geometry){
        if(geometry == null){
            return false;
        }
        Coordinate[] coordinates = null;
        if(geometry instanceof Polygon){
            Polygon polygon = (Polygon) geometry;
            //检查区域最外层点组成的大区域是否包含点
            if(!polygon.getEnvelope().contains(point)){
                return false;
            }
            coordinates = polygon.getExteriorRing().getCoordinates();
        }else if(geometry instanceof MultiPolygon){
            MultiPolygon multiPolygon = (MultiPolygon)geometry;
            coordinates = multiPolygon.getCoordinates();
        }

        int nCross = 0;
        for (int i = 0; i < coordinates.length; i++) {
            Coordinate current = coordinates[i];
            Coordinate next = coordinates[(i + 1) % coordinates.length];
            double dy1 = point.getY() - next.y, dy2 = point.getY() - current.y;
            // 多边形边界两点位于射线{ y = y0, x >= x0 }同侧
            if (dy1 * dy2 > 0) {
                continue;
            }
            // 多边形边界纵坐标位于射线{ y = y0, x >= x0 }异侧
            if (dy1 * dy2 < 0) {
                // 水平线，不计入
                if (Math.abs(current.y - next.y) < 0.00001) {
                    continue;
                } else {
                    double x = current.x + (point.getY() - current.y) * (current.x - next.x) / (current.y - next.y);
                    if (x >= point.getX()) {
                        nCross += 1;
                    }
                }
            }
        }
        return (nCross % 2 == 1);
    }

}
